﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using FunstreamTV.Model.Smile;
using FunstreamTV.Model.User;
using FunstreamTV.Tools;
using FunstreamTV.ViewModel.ObjectViewModel;
using Newtonsoft.Json.Linq;
using FunstreamTV.Model.Chat;
using FunstreamTV.Model.Content;
using FunstreamTV.Model.Stream;
using SM.Media.Content;
using SM.Media.MediaPlayer;
using SM.Media.Playlists;

namespace FunstreamTV.ViewModel
{
    public class StreamViewModel : BaseViewModel
    {
        public event EventHandler MessageAdded;
        private Visibility chatVisibility;

        public Visibility ChatVisibility
        {
            get { return chatVisibility; }
            set { chatVisibility = value; OnPropertyChanged(); }
        }

        public Visibility SmilesVisibility
        {
            get { return smilesVisibility; }
            set { smilesVisibility = value; OnPropertyChanged(); }
        }

        public Visibility SmilesButtonVisibility
        {
            get { return smilesButtonVisibility; }
            set { smilesButtonVisibility = value; OnPropertyChanged(); }
        }

        public Visibility PlayerButtonVisibility
        {
            get { return playerButtonVisibility; }
            set { playerButtonVisibility = value; OnPropertyChanged(); }
        }

        public Visibility ChatButtonVisibility
        {
            get { return chatButtonVisibility; }
            set { chatButtonVisibility = value; OnPropertyChanged(); }
        }

        public Visibility SettingsVisibility
        {
            get { return settingsVisibility; }
            set { settingsVisibility = value; OnPropertyChanged(); }
        }

        private ObservableCollection<ChatMessageViewModel> messages;
        private Visibility smilesVisibility;
        private ObservableCollection<ObservableCollection<SmileViewModel>> smiles;
        private Visibility smilesButtonVisibility;
        private string message;
        private SocketIOHelper socket;
        private Visibility recipientVisibility;
        private ChatFrom recipient;
        private Uri streamUri;

        public ObservableCollection<ChatMessageViewModel> Messages
        {
            get { return messages; }
            set { messages = value; OnPropertyChanged(); }
        }

        public string Message
        {
            get { return message; }
            set { message = value; OnPropertyChanged(); }
        }

        public Visibility RecipientVisibility
        {
            get { return recipientVisibility; }
            set { recipientVisibility = value; OnPropertyChanged(); }
        }

        public ObservableCollection<ObservableCollection<SmileViewModel>> Smiles
        {
            get { return smiles; }
            set { smiles = value; OnPropertyChanged(); }
        }

        public Uri StreamUri
        {
            get { return streamUri; }
            set { streamUri = value; OnPropertyChanged(); }
        }

        public Visibility PlayerVisibility
        {
            get { return playerVisibility; }
            set { playerVisibility = value; OnPropertyChanged(); }
        }

        public StreamViewModel()
        {
            ChatVisibility = Visibility.Collapsed;
            SmilesVisibility = Visibility.Collapsed;
            SmilesButtonVisibility = Visibility.Collapsed;
            RecipientVisibility = Visibility.Collapsed;
            PlayerVisibility = Visibility.Visible;
            ChatButtonVisibility = Visibility.Collapsed;
            PlayerButtonVisibility = Visibility.Collapsed;
        }

        public LoginResponse User { get; set; }

        public ChatFrom Recipient
        {
            get { return recipient; }
            set { recipient = value; OnPropertyChanged(); }
        }

        public List<Player> Players
        {
            get { return players; }
            set { players = value; OnPropertyChanged(); }
        }

        public List<QualityItem> Playlist
        {
            get { return playlist; }
            set { playlist = value; OnPropertyChanged(); }
        }

        public ContentViewModel CurrentStream;
        private Visibility playerVisibility;
        private Visibility playerButtonVisibility;
        private Visibility chatButtonVisibility;
        private Visibility settingsVisibility;
        private List<Player> players;
        private List<QualityItem> playlist;

        public async Task<bool> Load(ContentViewModel currentStream)
        {
            CurrentStream = currentStream;
            var requester = new Requester();
            var response = await requester.Post<List<List<SmileResponse>>, string>("/smile", String.Empty);
            if (response != null)
            {
                Smiles = new ObservableCollection<ObservableCollection<SmileViewModel>>();

                foreach (List<SmileResponse> smilesPage in response.Item)
                {
                    Smiles.Add(new ObservableCollection<SmileViewModel>(smilesPage.Select(j => new SmileViewModel
                    {
                        code = j.code,
                        image = j.image,
                        position = j.position,
                        usable = j.usable
                    })));
                }

                App.Smiles = new List<SmileViewModel>();
                foreach (var smile in Smiles)
                    App.Smiles.AddRange(smile);
            }
            var streamResponse = await requester.Post<StreamResponse, Stream>("/stream", new Stream { id = currentStream.streamer.id, options = new StreamOptions { players = true } });
            if (streamResponse.Item == null) return false;

            CurrentStream = new ContentViewModel {streamer = streamResponse.Item.streamer, players = streamResponse.Item.players };
            User = await GetUser();
            socket = new SocketIOHelper();
            socket.Connect(User.token, CurrentStream.streamer.id.ToString());
            socket.MessageAdded += Socket_MessageAdded;
            Players = CurrentStream.players;
            //SetPlayer(Players.);
            ShowChat();
            return true;
        }

        public async void SetPlayer(Player player, QualityItem quality)
        {
            if (CurrentStream.players != null)
            {
                
                if (player.name.ToUpper().Equals("CYBERGAME.TV"))
                {
                    StreamUri = await CyberGame.GetM3U8(player.channel);
                    ShowPlayer();
                    return;
                }
                
                if (player.name.ToUpper().Equals("GOODGAME.RU"))
                {
                    StreamUri = new Uri("http://hls.goodgame.ru/hls/" + player.channel + ".m3u8");
                    ShowPlayer();
                    return;
                }
                
                if (player.name.ToUpper().Equals("TWITCH.TV"))
                {
                    Playlist = await Twitch.GetM3U8(player.channel);
                    ShowPlayer();
                    return;
                }
            }
        }


        private void Socket_MessageAdded(object sender, EventArgs e)
        {
            Messages = socket.Messages;
            MessageAdded?.Invoke(this, new EventArgs());
        }

        public void ShowPlayer()
        {
            ChatButtonVisibility = Visibility.Visible;
            PlayerButtonVisibility = Visibility.Collapsed;
            ChatVisibility = Visibility.Collapsed;
            SmilesVisibility = Visibility.Collapsed;
            SmilesButtonVisibility = Visibility.Collapsed;
            PlayerVisibility = Visibility.Visible;
        }

        public void ShowChat()
        {
            ChatButtonVisibility = Visibility.Collapsed;
            PlayerButtonVisibility = Visibility.Visible;
            ChatVisibility = Visibility.Visible;
            SmilesVisibility = Visibility.Collapsed;
            SmilesButtonVisibility = Visibility.Visible;
            PlayerVisibility = Visibility.Visible;
        }

        public void ShowSmiles()
        {
            ChatButtonVisibility = Visibility.Collapsed;
            PlayerButtonVisibility = Visibility.Collapsed;
            ChatVisibility = Visibility.Collapsed;
            SmilesVisibility = Visibility.Visible;
            SmilesButtonVisibility = Visibility.Visible;
            PlayerVisibility = Visibility.Collapsed;
        }

        public async void SendMessage(int streamID, string text)
        {
            //код отправки
            var user = await GetUser();
            var jobject = new JObject
            {
                {"channel", "stream/" + streamID},
                {
                    "from", new JObject
                    {
                        {"id", user.current.id},
                        {"name", user.current.name}
                    }
                },
                {
                    "to", Recipient != null
                        ? new JObject
                        {
                            {"id", Recipient.id},
                            {"name", Recipient.name}
                        }
                        : null
                },
                {"text", text}
            };
            socket.SendMessage(jobject);
            Message = String.Empty;
            Recipient = null;
            RecipientVisibility = Visibility.Collapsed;
        }
    }
}